package com.phison.fenestrapro.dashboard;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.vaadin.Application;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.gwt.server.CommunicationManager;
import com.vaadin.ui.Window;

/**
 *
 * 
 * @author Niall O'Hara
 *
 */
@SuppressWarnings("serial")
public class SmartSessionCommunicationManager extends CommunicationManager {

	private Object smartSessionData;
	private FenestraProAppServlet servlet;
	private static final String EXTEND = "EXTEND";
	private static final String INVALIDATE = "INVALIDATE";

	public SmartSessionCommunicationManager(Application application,
			FenestraProAppServlet fenestraProAppServlet) {
		super(application);
		this.servlet = fenestraProAppServlet;
	}

	private int sessionTimeoutSeconds = -1;
	public static final String COOKIE_NAME = "SmartSessionData";

	protected int detectSessionTimout(HttpSession session) {
		if (sessionTimeoutSeconds == -1) {
			String initParameter = servlet
					.getInitParameter("SmartSessionTimeout");
			if (initParameter != null) {
				int smt = (int) (Float.parseFloat(initParameter) * 60);
				sessionTimeoutSeconds = smt;
			}
			if (sessionTimeoutSeconds == -1) {
				// if not overridden, use the value from session
				// TODO session vs. application timeout mode
				sessionTimeoutSeconds = session.getMaxInactiveInterval();
			}
		}
		return sessionTimeoutSeconds;
	}

	@Override
	protected void doHandleUidlRequest(Request request, Response response,
			Callback callback, Window window) throws IOException,
			InvalidUIDLSecurityKeyException {
		smartSessionData = request
				.getAttribute(SmartSessionCommunicationManager.COOKIE_NAME);

		super.doHandleUidlRequest(request, response, callback, window);
	}

	@Override
	public void writeUidlResponce(Callback callback, boolean repaintAll,
			PrintWriter outWriter, Window window, boolean analyzeLayouts)
			throws PaintException {
		// TODO Auto-generated method stub
		super.writeUidlResponce(callback, repaintAll, outWriter, window,
				analyzeLayouts);
		if (smartSessionData != null) {
			outWriter.print(",\""
					+ SmartSessionCommunicationManager.COOKIE_NAME + "\" :\"");
			outWriter.print(smartSessionData);
			outWriter.print("\"");
			if (repaintAll) {
				outWriter.print(",\"" + COOKIE_NAME + "-timeout\":"
						+ sessionTimeoutSeconds);
			}
		}
	}

	boolean handleSmartSession(HttpServletRequest request,
			HttpServletResponse response, boolean uidlrequest) {
		HttpSession session = request.getSession(false);
		if (session != null) {
			if (sessionTimeoutSeconds == -1) {
				detectSessionTimout(session);
			}
			// TODO maxInactiveInterva vs. sessionTi
			int sessionRemaining = session.getMaxInactiveInterval();
			long lastAccessedTime = session.getLastAccessedTime();
			if (uidlrequest && request.getParameter(EXTEND) != null) {
				// TODO to avoid collisions (probably very rare ones) add
				// the last accessed time known by the client and verify it
				// is the same as here previousAccessTime.
				long extendTo = Long.parseLong(request.getParameter(EXTEND));
				// System.err.println("Making session die at "
				// + new Date(extendTo));
				sessionRemaining = (int) ((extendTo - lastAccessedTime) / 1000);
				// System.err.println("Session remaining to:" +
				// sessionRemaining);
				session.setMaxInactiveInterval(sessionRemaining);
			} else if (request.getParameter(INVALIDATE) != null) {
				// TODO verify that no other request has been active if in
				// "session" mode
				// TODO application termination if in "app mode"
			}

			// System.err.println();
			// System.err.println("Now:" + new Date());
			// System.err.println("Last-Accessed:" + lastAccessedTime + " "
			// + new Date(lastAccessedTime));
			// System.err.println("Prev-Accessed:" + previousAcceesTime + " "
			// + new Date(previousAcceesTime));
			String cookie = "" + (lastAccessedTime + sessionRemaining*1000);
			// System.err.println("Cookie:" + cookie);
			if (uidlrequest) {
				request.setAttribute(COOKIE_NAME, cookie);
				response.addHeader(COOKIE_NAME, cookie);
			} else {
				Cookie c = new Cookie(COOKIE_NAME, cookie);
				response.addCookie(c);
			}

		}
		return true;
	}

}